﻿#region Using Statements
using System;
using System.Collections.Generic;
using DirectZZT.Shared.Input;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
#endregion

namespace DirectZZT.Input
{
    /// <summary>
    /// Provides an input manager for the gamepad.
    /// </summary>
    public class GamepadInputManager : IInputManager
    {
        #region Fields

        private GamePadState _gpPrevious;
        private GamePadState _gpCurrent;

        private Dictionary<string, InputCommand> _commands;
        private Dictionary<string, Buttons> _inputBindings;
        private Vector2 _cursor;

        #endregion

        #region Properties

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the GamepadInputManager class.
        /// </summary>
        public GamepadInputManager()
        {
            _inputBindings = new Dictionary<string, Buttons>();
            _commands = new Dictionary<string, InputCommand>();

            _gpPrevious = GamePad.GetState(PlayerIndex.One);
            _gpCurrent = _gpPrevious;
        }

        #endregion

        #region Methods

        #endregion

        #region IInputManager Members

        InputManagerDevices IInputManager.HandledDevices
        {
            get { return InputManagerDevices.Gamepad; }
        }

        /// <summary>
        /// Gets/sets the cursor position.
        /// </summary>
        public Vector2 CursorPosition
        {
            get { return _cursor; }
            set { _cursor = value; }
        }

        IEnumerable<InputBinding> IInputManager.GetBindings()
        {
            foreach (var item in _inputBindings)
            {
                yield return new InputBinding() { Action = item.Key, Code = (int)item.Value };
            }
        }

        void IInputManager.Bind(string action, int code)
        {
            // TODO: silly. doesn't allow for multiple bindings to the same action. prio 3
            _inputBindings[action] = (Buttons)code;
        }

        void IInputManager.UnBind(string action)
        {
            _inputBindings.Remove(action);
        }

        void IInputManager.RegisterCommand(string name, InputCommand command)
        {
            _commands[name] = command;
        }

        bool IInputManager.GetActionInvoked(string action)
        {
            if (!_inputBindings.ContainsKey(action))
            {
                return false;
            }

            Buttons button = _inputBindings[action];

            return _gpCurrent.IsButtonDown(button);
        }

        bool IInputManager.GetActionInvokedToggle(string action)
        {
            if (!_inputBindings.ContainsKey(action))
            {
                return false;
            }

            Buttons button = _inputBindings[action];

            return _gpCurrent.IsButtonDown(button) && _gpPrevious.IsButtonUp(button);
        }

        float IInputManager.GetActionValue(string action)
        {
            if (!_inputBindings.ContainsKey(action))
            {
                return 0.0f;
            }

            Buttons button = _inputBindings[action];

            return _gpCurrent.IsButtonDown(button) ? 1.0f : 0.0f;
        }

        bool IInputManager.IsAnyKey()
        {
            // dunno if this is required anymore
            return false;
        }

        void IInputManager.Update()
        {
            _gpPrevious = GamePad.GetState(PlayerIndex.One);
            _gpCurrent = _gpPrevious;

            // change cursor - currently only via DPAD
            // the values are determined by fair dice roll
            if (_gpCurrent.DPad.Up == ButtonState.Pressed)
            {
                if (_cursor.X > 0.0f && _cursor.X < 100.0f)
                {
                    _cursor.X -= 0.1f;
                }
            }
            if (_gpCurrent.DPad.Down == ButtonState.Pressed)
            {
                if (_cursor.X > 0.0f && _cursor.X < 100.0f)
                {
                    _cursor.X += 0.1f;
                }
            }
            if (_gpCurrent.DPad.Left == ButtonState.Pressed)
            {
                if (_cursor.Y > 0.0f && _cursor.Y < 100.0f)
                {
                    _cursor.Y -= 0.133f;
                }
            }
            if (_gpCurrent.DPad.Right == ButtonState.Pressed)
            {
                if (_cursor.Y > 0.0f && _cursor.Y < 100.0f)
                {
                    _cursor.Y += 0.133f;
                }
            }
        }

        #endregion

        #region IDisposable Members

        void IDisposable.Dispose()
        {

        }

        #endregion
    }
}
